home *** CD-ROM | disk | FTP | other *** search
- unit Changeu;
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables;
-
- const
- wm_TableChanged = wm_User + 57;
-
- type
- TForm1 = class(TForm)
- Table1: TTable;
- DataSource1: TDataSource;
- DBGrid1: TDBGrid;
- procedure FormDestroy(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- private
- { Private declarations }
- FOldCallBack: TCallBack;
- FChangeFunctionThunk: TFarProc;
- public
- { Public declarations }
- procedure WMTableChanged(var Msg: TMessage); message wm_TableChanged;
- end;
-
- var
- Form1: TForm1;
-
- implementation
-
- uses
- DbiTypes, DbiProcs;
-
- {$R *.DFM}
-
- function FindPrevInstanceProc(Wnd: HWnd; UserData: Longint): Bool; export;
- var
- WndClass, WndText: array[0..255] of char;
- begin
- Result := True;
- { Concentrate solely on our EXE }
- if GetWindowWord(Wnd, gww_HInstance) = HPrevInst then
- begin
- GetClassName(Wnd, WndClass, Pred(SizeOf(WndClass)));
- GetWindowText(Wnd, WndText, Succ(Length(Application.MainForm.Caption)));
- { Normally first window will be Application's }
- { But if the app started minimised, it will be the main form's }
- if (StrPas(WndClass) = Application.ClassName) or
- ((StrPas(WndText) = Application.MainForm.Caption) and
- IsIconic(Wnd)) then
- begin
- { This technique is used by the VCL - post a messge }
- { then bring the window to the top, before the message }
- { gets processed }
- PostMessage(Wnd, wm_SysCommand, sc_Restore, 0);
- BringWindowToTop(Wnd);
- Halt;
- end;
- end;
- end;
-
- function ChangeFunction(ecbType: CBType; iClientData: Longint;
- var CbInfo: Pointer): CBRType; export;
- begin
- Result := cbrUseDef;
- if ecbType = cbTableChanged then
- PostMessage(Application.MainForm.Handle, wm_TableChanged, 0, iClientData);
- with Form1.FOldCallBack do
- if ChainedFunc <> nil then Result :=
- pfDBICallBack(ChainedFunc)(cbTableChanged, Data, Buffer)
- end;
-
- procedure ChangeFunctionThunk; assembler;
- asm
- mov ax, seg @Data
- { Bypass the smart callback instruction }
- jmp ChangeFunction + 3
- end;
-
- procedure TForm1.FormCreate(Sender: TObject);
- begin
- if HPrevInst <> 0 then
- EnumWindows(@FindPrevInstanceProc, 0);
- FChangeFunctionThunk := @ChangeFunctionThunk;
- with FOldCallBack do
- DbiGetCallBack(nil, cbTableChanged, Data, BufLen, Buffer, @ChainedFunc);
- DbiRegisterCallBack(Table1.Handle, cbTableChanged, Longint(Table1), 0, nil,
- pfDbiCallback(FChangeFunctionThunk));
- end;
-
- procedure TForm1.FormDestroy(Sender: TObject);
- begin
- DbiRegisterCallBack(Table1.Handle, cbTableChanged, 0, 0, nil, nil);
- end;
-
- procedure TForm1.WMTableChanged(var Msg: TMessage);
- begin
- if MessageDlg(TTable(Msg.LParam).TableName + ' has changed - refresh?',
- mtConfirmation, [mbYes, mbNo], 0) = mrYes then
- TTable(Msg.LParam).Refresh;
- end;
-
- end.
-